home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / dejagnu.lha / dejagnu-1.0.1 / expect / pty_termios.c < prev    next >
C/C++ Source or Header  |  1993-04-15  |  8KB  |  337 lines

  1. /* pty_termios.c - routines to allocate ptys - termios version
  2.  
  3. Written by: Don Libes, NIST, 2/6/90
  4.  
  5. Design and implementation of this program was paid for by U.S. tax
  6. dollars.  Therefore it is public domain.  However, the author and NIST
  7. would appreciate credit if this program or parts of it are used.
  8.  
  9. */
  10.  
  11. #include "exp_conf.h"
  12. #ifdef HAVE_UNISTD_H
  13. #  include <unistd.h>
  14. #endif
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17.  
  18. #ifdef HAVE_SYSMACROS_H
  19. #include <sys/sysmacros.h>
  20. #endif
  21.  
  22. #ifdef HAVE_PTYTRAP
  23. #include <sys/ptyio.h>
  24. #endif
  25.  
  26. #include <sys/file.h>
  27.  
  28. #ifdef HAVE_SYS_FCNTL_H
  29. #  include <sys/fcntl.h>
  30. #else
  31. #  include <fcntl.h>
  32. #endif
  33.  
  34. #ifdef HAVE_PTMX
  35. #  include <sys/stropts.h>
  36. #endif
  37.  
  38. #include "exp_tty.h"
  39. #include "exp_rename.h"
  40. #include "exp_pty.h"
  41.  
  42. void debuglog();
  43.  
  44. extern int errno;
  45. extern char *sys_errlist[];
  46.  
  47. #ifndef TRUE
  48. #define TRUE 1
  49. #define FALSE 0
  50. #endif
  51.  
  52. #if defined(HAVE__GETPTY) || defined(HAVE_PTC) || defined(HAVE_PTC_PTS) || defined(HAVE_PTMX)
  53. static char *slave_name;
  54. #endif
  55.  
  56. #if defined(HAVE_GETPTY)
  57. #include <sys/vty.h>
  58. static char    master_name[MAXPTYNAMELEN];
  59. static char    slave_name[MAXPTYNAMELEN];
  60. #endif
  61.  
  62. #if !defined(HAVE_GETPTY) && !defined(HAVE_GETPTY) && !defined(HAVE_PTC) && !defined(HAVE_PTC_PTS) && !defined(HAVE_PTMX)
  63. #ifdef HAVE_PTYM
  64. static char    master_name[] = "/dev/ptym/ptyXX";
  65. static char    slave_name[] = "/dev/pty/ttyXX";
  66. static char    *slave_bank;
  67. static char    *slave_num;
  68. #else
  69. static char    master_name[] = "/dev/ptyXX";
  70. static char    slave_name [] = "/dev/ttyXX";
  71. #endif
  72. #endif
  73.  
  74. static char    *tty_type;        /* ptr to char [pt] denoting
  75.                        whether it is a pty or tty */
  76. static char    *tty_bank;        /* ptr to char [p-z] denoting
  77.                        which bank it is */
  78. static char    *tty_num;        /* ptr to char [0-f] denoting
  79.                        which number it is */
  80. static void
  81. pty_stty(s,name)
  82. char *s;        /* args to stty */
  83. char *name;        /* name of pty */
  84. {
  85. #define MAX_ARGLIST 10240
  86.     char buf[MAX_ARGLIST];    /* overkill is easier */
  87.  
  88.     sprintf(buf,"stty %s < %s > %s",s,name,name);
  89.     system(buf);
  90. }
  91.  
  92. exp_tty exp_tty_original;
  93.  
  94. int dev_tty;        /* file descriptor to /dev/tty or -1 if none */
  95. int knew_dev_tty;    /* true if we had our hands on /dev/tty at any time */
  96.  
  97. #define GET_TTYTYPE    0
  98. #define SET_TTYTYPE    1
  99. static void
  100. ttytype(request,fd,ttycopy,ttyinit,s)
  101. int request;
  102. int fd;
  103.         /* following are used only if request == SET_TTYTYPE */
  104. int ttycopy;    /* true/false, copy from /dev/tty */
  105. int ttyinit;    /* if true, initialize to sane state */
  106. char *s;    /* stty args */
  107. {
  108.     if (request == GET_TTYTYPE) {
  109. #ifdef POSIX
  110.         if (-1 == tcgetattr(fd, &exp_tty_original)) {
  111. #else
  112.         if (-1 == ioctl(fd, TCGETS, (char *)&exp_tty_original)) {
  113. #endif
  114.             knew_dev_tty = FALSE;
  115.             dev_tty = -1;
  116.         }
  117.     } else {    /* type == SET_TTYTYPE */
  118.         if (ttycopy && knew_dev_tty) {
  119. #ifdef POSIX
  120.             (void) tcsetattr(fd, TCSADRAIN, &exp_tty_original);
  121. #else
  122.             (void) ioctl(fd, TCSETS, (char *)&exp_tty_original);
  123. #endif
  124.         }
  125.  
  126. #ifdef __SABER__
  127. #undef DFLT_STTY
  128. #define DFLT_STTY "sane"
  129. #endif
  130.         if (ttyinit) {
  131.             /* overlay parms originally supplied by Makefile */
  132.             debuglog("getptyslave: (default) stty %s\n",DFLT_STTY);
  133.             pty_stty(DFLT_STTY,slave_name);
  134.         }
  135.  
  136.         /* lastly, give user chance to override any terminal parms */
  137.         if (s) {
  138.             /* give user a chance to override any terminal parms */
  139.             debuglog("getptyslave: (user-requested) stty %s\n",s);
  140.             pty_stty(s,slave_name);
  141.         }
  142.     }
  143. }
  144.  
  145. void
  146. init_pty()
  147. {
  148. #if !defined(HAVE_GETPTY) && !defined(HAVE_GETPTY) && !defined(HAVE_PTC) && !defined(HAVE_PTC_PTS) && !defined(HAVE_PTMX)
  149. #ifdef HAVE_PTYM
  150.     static char dummy;
  151.     tty_bank = &master_name[strlen("/dev/ptym/pty")];
  152.     tty_num  = &master_name[strlen("/dev/ptym/ptyX")];
  153.     slave_bank = &slave_name[strlen("/dev/pty/tty")];
  154.     slave_num  = &slave_name[strlen("/dev/pty/ttyX")];
  155. #else
  156.     tty_bank = &master_name[strlen("/dev/pty")];
  157.     tty_num  = &master_name[strlen("/dev/ptyp")];
  158.     tty_type =   &slave_name[strlen("/dev/")];
  159. #endif
  160.  
  161. #endif /* HAVE_PTYM */
  162.  
  163.  
  164.     dev_tty = open("/dev/tty",O_RDWR);
  165.     knew_dev_tty = (dev_tty != -1);
  166.     if (knew_dev_tty) ttytype(GET_TTYTYPE,dev_tty,0,0,(char *)0);
  167. }
  168.  
  169. #ifndef R_OK
  170. /* 3b2 doesn't define these according to jthomas@nmsu.edu. */
  171. #define R_OK 04
  172. #define W_OK 02
  173. #endif
  174.  
  175. int
  176. getptymaster()
  177. {
  178.     char *hex, *bank;
  179.   struct stat stat_buf;
  180.     int master = -1;
  181.  
  182. #if defined(HAVE_PTMX)
  183.     if ((master = open("/dev/ptmx", O_RDWR)) == -1) return(-1);
  184.     if ((slave_name = ptsname(master)) == NULL || unlockpt(master) || grantpt(master)) {
  185.         close(master);
  186.         return(-1);
  187.     }
  188.     (void) ioctl(master,TIOCFLUSH,(char *)0);
  189.  
  190.     return(master);
  191. #endif
  192.  
  193. #if defined(HAVE__GETPTY)        /* SGI needs it this way */
  194.     slave_name = _getpty(&master, O_RDWR, 0600, 0);
  195.     if (slave_name == NULL)
  196.      return (-1);    
  197.     return(master);
  198. #endif
  199.  
  200. #if defined(HAVE_PTC) && !defined(HAVE__GETPTY)    /* old SGI, version 3 */
  201.     master = open("/dev/ptc", O_RDWR);
  202.     if (master >= 0) {
  203.      int ptynum;
  204.  
  205.         if (fstat(master, &stat_buf) < 0) {
  206.             close(master);
  207.        return(-1);
  208.      }
  209.      ptynum = minor(stat_buf.st_rdev);
  210.         sprintf(slave_name,"/dev/ttyq%d",ptynum);
  211.    }
  212.     return(master);
  213. #endif
  214.  
  215. #if defined(HAVE_GETPTY) && !defined(HAVE__GETPTY)
  216.     master = getpty(master_name, slave_name, O_RDWR);
  217.     /* is it really necessary to verify slave side is usable? */
  218.     return master;
  219. #endif
  220.  
  221. #if defined(HAVE_PTC_PTS)
  222.     master = open("/dev/ptc",O_RDWR);
  223.     if (master >= 0) {
  224.         /* never fails */
  225.         slave_name = ttyname(master);
  226.     }
  227.     return(master);
  228. #endif
  229.  
  230. #if !defined(HAVE_GETPTY) && !defined(HAVE_GETPTY) && !defined(HAVE_PTC) && !defined(HAVE_PTC_PTS) && !defined(HAVE_PTMX)
  231.     if (exp_pty_test_start() == -1) return -1;
  232.  
  233.     for (bank = "pqrstuvwxyzPQRSTUVWXYZ";*bank;bank++) {
  234.         *tty_bank = *bank;
  235.     *tty_num = '0';
  236.         if (stat(master_name, &stat_buf) < 0) break;
  237.     for (hex = "0123456789abcdef";*hex;hex++) {
  238.       *tty_num = *hex;
  239. #ifdef HAVE_PTYM
  240.     *slave_bank = *tty_bank;
  241.     *slave_num = *tty_num;
  242. #else
  243.             strcpy(slave_name,master_name);
  244.     *tty_type = 't';
  245. #endif
  246.             master = exp_pty_test(master_name,slave_name,*tty_bank,*tty_num);
  247.             if (master >= 0) goto done;
  248.         }
  249.     }
  250.  done:
  251. #ifdef HAVE_PTYTRAP
  252.     /* Turn on trapping of close, open and */
  253.     /* ioctl requests from the slave.*/
  254.     {
  255.         int enable = 1;
  256.     ioctl(master, TIOCTRAP, &enable);
  257.     }
  258. #endif /* HAVE_PTYTRAP */
  259.  
  260.     exp_pty_test_end();
  261.     return(master);
  262. #endif
  263. }
  264.  
  265. int
  266. getptyslave(ttycopy,ttyinit,stty_args)
  267. int ttycopy;
  268. int ttyinit;
  269. char *stty_args;
  270. {
  271.     int slave;
  272.     if (0 > (slave = open(slave_name, O_RDWR))) return(-1);
  273.  
  274. #if defined(HAVE_PTMX)
  275.     if (ioctl(slave, I_PUSH, "ptem")) {
  276.         debuglog("ioctl(%s,I_PUSH,\"ptem\") = %s\n",sys_errlist[errno]);
  277.     }
  278.     if (ioctl(slave, I_PUSH, "ldterm")) {
  279.         debuglog("ioctl(%s,I_PUSH,\"ldterm\") = %s\n",sys_errlist[errno]);
  280.     }
  281.     if (ioctl(slave, I_PUSH, "ttcompat")) {
  282.         debuglog("ioctl(%s,I_PUSH,\"ttcompat\") = %s\n",sys_errlist[errno]);
  283.     }
  284. #endif
  285.  
  286.     /* sanity check - if slave not 0, skip rest of this and return */
  287.     /* to what will later be detected as an error in caller */
  288.     if (0 != slave) return(slave);
  289.  
  290.     fcntl(0,F_DUPFD,1);    /* duplicate 0 onto 1 to prepare for stty */
  291.     ttytype(SET_TTYTYPE,slave,ttycopy,ttyinit,stty_args);
  292.     (void) exp_pty_unlock();
  293.     return(slave);
  294. }
  295.  
  296. #ifdef HAVE_PTYTRAP
  297. #include <sys/ptyio.h>
  298. #include <sys/time.h>
  299.  
  300. /* return 1 for failure, 0 for success */
  301. int
  302. exp_wait_for_slave_open(fd)
  303. int fd;
  304. {
  305.     fd_set excep;
  306.     struct timeval t;
  307.     struct request_info ioctl_info;
  308.     int rc;
  309.  
  310.     int maxfds = sysconf(_SC_OPEN_MAX);
  311.  
  312.     t.tv_sec = 30;    /* 30 seconds */
  313.     t.tv_usec = 0;
  314.  
  315.     FD_ZERO(&excep);
  316.     FD_SET(fd,&excep);
  317.  
  318.     rc = select(maxfds,(fd_set *)0,(fd_set *)0,&excep,&t);
  319.     if (rc != 1) {
  320.         debuglog("spawned process never started, errno = %d\n",errno);
  321.         return(1);
  322.     }
  323.     if (ioctl(fd,TIOCREQCHECK,&ioctl_info) < 0) {
  324.         debuglog("ioctl(TIOCREQCHECK) failed, errno = %d\n",errno);
  325.         return(1);
  326.     }
  327.     if (ioctl_info.request != TIOCOPEN) {
  328.         debuglog("ioctl from slave is not OPEN?\n");
  329.     }
  330.     if (ioctl(fd, TIOCREQSET, &ioctl_info) < 0) {
  331.         debuglog("ioctl(TIOCREQSET) failed, errno = %d\n",errno);
  332.         return(1);
  333.     }
  334.     return(0);    
  335. }
  336. #endif
  337.